// LocalHookDemo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "iostream"
#include <easyhook.h>

using namespace std;

#pragma comment(lib, "EasyHook32.lib")

extern "C" DRIVER_SHARED_API(NTSTATUS, LhInstallHook(void* InEntryPoint,void* InHookProc,void* InCallback,TRACED_HOOK_HANDLE OutHandle));
extern "C" EASYHOOK_NT_EXPORT LhSetExclusiveACL(ULONG* InThreadIdList,ULONG InThreadCount,TRACED_HOOK_HANDLE InHandle);
extern "C" EASYHOOK_NT_EXPORT LhSetInclusiveACL(ULONG* InThreadIdList,ULONG InThreadCount,TRACED_HOOK_HANDLE InHandle);
extern "C" DRIVER_SHARED_API(PWCHAR, RtlGetLastErrorString());

DWORD gFreqOffset = 0;
BOOL WINAPI myBeepHook(DWORD dwFreq, DWORD dwDuration)
{
	std::cout << "\n    BeepHook: ****All your beeps belong to us!\n\n";
	Beep(dwFreq + gFreqOffset, dwDuration);
	return 0;
}

DWORD WINAPI MyHookFunction( LPVOID pParam )
{
	HOOK_TRACE_INFO hHook = { NULL };
	NTSTATUS result = LhInstallHook(
		GetProcAddress(GetModuleHandle(TEXT("kernel32")), "Beep"),
		myBeepHook,
		NULL,
		&hHook);
	if (FAILED(result))
	{
		std::wstring s(RtlGetLastErrorString());
		std::wcout << L"NativeInjectionEntryPoint: Failed to install hook: " << s.c_str() << endl;
	}
	else 
	{
		std::cout << "NativeInjectionEntryPoint: Hook 'myBeepHook installed successfully.\n";
	}

	// If the threadId in the ACL is set to 0,
	// then internally EasyHook uses GetCurrentThreadId()
	ULONG ACLEntries[1] = { 0 };

	// Disable the hook for the provided threadIds, enable for all others
	LhSetExclusiveACL(ACLEntries, 1, &hHook);
	//LhSetInclusiveACL(ACLEntries, 1, &hHook);

	cout << "call hooked Beep ret: " << Beep(10000, 100) << endl;
	return 1;
}


int _tmain(int argc, _TCHAR* argv[])
{
	cout << "begin localhook demo call Beep No Hook" << endl;
	Beep(10000, 1000);

	CreateThread(0,0,MyHookFunction,0,0,0);
	cout << "begin thread success" << endl;
	cin >> gFreqOffset;
	cout << "call hooked Beep ret: " << Beep(10000, 100) << endl;
	return 0;
}

